﻿function ajaxGrid(e) {
	var _this = this;
	this.id = $(e).attr('id');
	this.loadingId = this.id + '-loading';
	this.pagerId = this.id + '-pager';
	this.noDataId = this.id + '-nodata';
	this.errorMessageId = this.id + '-errormessage';
	this.totalRowCount = 0;
	this.headings=[]
	this.data = [];
	this.page = 0;
	this.pageCount = 1;
	this.pageGroup = 0;
	this.pageGroupSize = 5;
	this.rowsPerPage = parseInt($(e).attr('rowsperpage'));
	this.href = $(e).attr('href');
	this.delayLoading = $(e).attr('delayloading') == 'true';
	this.rowUrl = $(e).attr('rowurl');
	this.onclick = $(e).attr('onclick');
	this.rowDynamicCss = $(e).attr('rowdynamiccss');
	this.idColumn = 'Id';
	this.noData = $(e).attr('nodata');
	this.errorMessage = $(e).attr('errormessage');
	this.parameters = $(e).attr('parameters');
	this.oncomplete = $(e).attr('oncomplete');
	if (!this.errorMessage)
		this.errorMessage = 'An error occurred while retrieving the data for the grid.';
	this.groupBy = $(e).attr('groupby');
	if(this.groupBy)
		this.groups = this.groupBy.split(',');

	this.setTotalCount = function (tc)	//Set the TotalCount, and recalc the pageCount
	{
		this.totalRowCount = tc;
		this.pageCount = 1;
		if (!isNaN(this.rowsPerPage)) {
			this.pageCount = parseInt(this.totalRowCount / this.rowsPerPage);
			if ((tc % this.rowsPerPage) > 0)
				this.pageCount++;
		}
		if (this.page > 0 && this.page > (this.pageCount - 1))		//Make sure the Current Page is never greater than the pageCount
			this.page = (this.pageCount - 1);
	}
	this.getPage = function (p)		//Get the Data for Page p
	{
		var pgs = this.pageGroupSize;
		var pc = this.pageCount;
		if (p < 0)
			p = 0;
		if (p >= pc)
			p = pc - 1;
		var gr = this.getPageGroupRange();
		if (p < gr.s || p >= gr.e)
			this.pageGroup = parseInt(p / pgs);
		this.page = p;
		this.getData();
	}
	this.getPageGroup = function (g) {
		var pgs = this.pageGroupSize;
		var p;
		if (g > this.pageGroup)
			p = (g * pgs);
		else
			p = ((g + 1) * pgs) - 1;
		this.pageGroup = g;
		this.getPage(p);
	}
	this.getPageGroupRange = function () {
		var c = this.pageCount;
		var pgs = this.pageGroupSize;
		var si = (this.pageGroup * pgs);
		if (si >= c)
			si = (c - pgs) >= 0 ? c - pgs : 0; 			//min index 0 based
		var ei = (si + pgs) > c ? c : si + pgs; 			//max index+1
		return { s: si, e: ei }
	}
	this.showLoading = function () {
		$('#'+this.noDataId).hide();
		$('#'+this.errorMessageId).hide();
		var div = $('#' + this.loadingId);
		if (div.length == 0) {
			div = $('<div id="' + this.loadingId + '">').addClass('ajax-grid-loading');
			$(e).after(div);
		}
		var pager = $('#' + this.pagerId);
		var w = $(e).outerWidth(true);
		var h = $(e).outerHeight(true) + pager.outerHeight(true);
		div.width(w);
		div.height(h);
		div.show();
		pager.hide();
		$(e).hide();
	}
	this.getData = function () {
		this.showLoading();

		if (!this.href) {
			alert('No href set on ajaxGrid ' + this.id);
			return;
		}
		var req = {};
		if (this.parameters)
			$.extend(true, req, $.getData(this.parameters));
		$.extend(true, req, { page: this.page, rowsperpage: this.rowsPerPage });
		$.post(
				this.href,
				req,
				function (data) { _this.setData(data); })
			.fail(function () {
				_this.setData({Success: false});
			});

	}
	this.setData = function (r) {
		$('#' + this.loadingId).hide();
		$('#' + this.errorMessageId).remove();
		$('#' + this.noDataId).remove();
		$(e).hide();
		if (!r.Success) {
			$(e).after('<div id="' + this.errorMessageId + '" class="ajax-grid-error">' + this.errorMessage + '</div>');
			return;
		}
		this.data = r.Data;
		if ((this.data == null || this.data.length == 0) && this.noData != null) {
			$(e).after('<div id="' + this.noDataId + '" class="ajax-grid-info">' + this.noData + '</div>');
			return;
		}
		this.setTotalCount(r.TotalCount);
		this.render();
		if (this.oncomplete && window[this.oncomplete] != null)
			window[this.oncomplete]();
	}
	this.render = function () {
		$(e).find('tbody > tr.dynamic').remove();
		var ctx = {};
		ctx.groups = {};
		ctx.grouped = {};
		if (this.groups) {
			var gc = this.groups.length;
			for (var i = 0; i < gc; i++) {
				var name = this.groups[i];
				var g = {
					name: name,
					parent: null,
					isMatch: function (r, v) {
						if (v == null)
							v = this.current;
						return (v == r[this.name]) && (this.parent == null || this.parent.isMatch(r));
					},
					resetChildren: function () {
						if (this.child) {
							this.child.current = null;
							this.child.resetChildren();
						}
					}
				};
				if (i > 0)
					g.parent = ctx.groups[this.groups[i - 1]];
				ctx.groups[name] = g;
			}
			for (var i = 0; i < gc; i++) {
				var name = this.groups[i];
				var g = ctx.groups[name];
				if (i < (gc - 1))
					g.child = ctx.groups[this.groups[i + 1]];
			}
		}
		$.each(this.data, function (i, r) { _this.renderRow(i, r, ctx); });
		this.setSelectedIds(this.selectedIds);
		$(e).show();
		this.renderPager();
	}
	this.renderRow = function (i, r, ctx) {
		var row = $('<tr>').addClass('dynamic');
		var rowData = _this.data[i];

		if (this.rowDynamicCss && window[this.rowDynamicCss]) {
			var dcss = window[this.rowDynamicCss](rowData);
			if (dcss)
				row.addClass(dcss);
		}

		if (i % 2 == 1)
			row.addClass('alt');

		if (this.rowUrl) {
			row.addClass('link');
			row.click(function () {
				if (_this.rowUrl) {
					location.href = _this.rowUrl + '/' + rowData[_this.idColumn];
					return;
				}
			});
		}

		if(this.onclick)
		{
			row.click(function (){
				if(window[_this.onclick])
					window[_this.onclick](r);
			});
		}

		var tableBody = $(e).find('tbody');
		if (tableBody == null)
			tableBody = $(e);
		tableBody.append(row);
		$.each(this.headings, function (ci, h) {
			_this.renderCell(ci, h, row, rowData, ctx);
		});
	}
	this.renderCell = function (i, h, row, rowData, ctx) {
		var g = ctx.groups[h.bind];
		var v = rowData[h.bind];
		var rowSpan = 0;
		if (g) {
			if (v != g.current) {
				g.current = v;
				g.resetChildren();
				for (var i = 0; i < this.data.length; i++) {
					if (g.isMatch(this.data[i], v))
						rowSpan++;
				}
			}
			else
				return;
		}
		if (h.groupby) {
			g = ctx.groups[h.groupby]
			if (!ctx.grouped[h.bind])
				ctx.grouped[h.bind] = {};
			var valKey = g.current + '-' + v;
			if (ctx.grouped[h.bind][valKey])
				return;
			var rs = row.children('td[bind="' + h.groupby + '"]').attr('rowspan');
			if (rs)
				rowSpan = parseInt(rs);
			ctx.grouped[h.bind][valKey] = true;
		}
		var cell = $('<td>');
		cell.attr('bind', h.bind);
		if (rowSpan > 1)
			cell.attr('rowspan', rowSpan);
		if (h.format)
			cell.attr('format', h.format);
		if (h.type)
			cell.attr('type', h.type);

		if (h.maxlength && v.length > h.maxlength) {
			var t = v.replace(/\"/g, '&quot;').replace(/<br>/g, '\r\n');
			cell.attr('title', t);
			if (h.maxlengthalign == 'right')
				v = '...' + v.substring(v.length - h.maxlength);
			else
				v = v.substring(0, h.maxlength) + '...';
		}

		if (h.type == "selector")
			cell.html('<input type="checkbox" class="' + this.id + '-selector" data-id="' + v + '"/>')
		else
			cell.setFormattedContent(v, rowData);

		if (h.cellcss)
			cell.attr('class', h.cellcss);
		if (h.cellstyle)
			cell.attr('style', h.cellstyle);

		row.append(cell);
	}
	this.renderPager = function () {
		if (isNaN(this.rowsPerPage) || this.totalRowCount < 2 || this.pageCount < 2)
			return;		
		var pager = $('#' + this.pagerId);
		if (pager.length == 0) {
			var pager = $('<div id="' + this.pagerId + '" class="ajax-grid-pager">');
		}
		pager.empty();
		$(e).after(pager);

		var gr = this.getPageGroupRange();

		var ul = $('<ul>');
		pager.append(ul);

		if (this.page > 0) {	//first & previous
			ul.append(
				$('<li >').append(
					$('<a>').addClass('first').html('<< first').attr('href', 'javascript:' + this.id + '.getPage(0)')));
			ul.append(
				$('<li>').append(
					$('<a>').html('< previous').attr('href', 'javascript:' + this.id + '.getPage(' + (this.page-1) + ')')));
		}
		if (this.pageCount > this.pageGroupSize && this.pageGroup > 0)	//previous page group
			ul.append(
				$('<li>').append(
					$('<a>').html('...').attr('href', 'javascript:' + this.id + '.getPageGroup(' + (this.pageGroup - 1) + ')')));
		for (var i = gr.s; i < gr.e; i++)	//pages
		{
			ul.append(
				$('<li>').addClass(i == this.page ? 'active' : '').append(
					$('<a>').html(i + 1).attr('href','javascript:'+this.id+'.getPage('+i+')')));
		}
		if (gr.e < this.pageCount)	//next page group
			ul.append(
				$('<li>').append(
					$('<a>').html('...').attr('href', 'javascript:' + this.id + '.getPageGroup(' + (this.pageGroup + 1) + ')')));
		if (this.page < this.pageCount - 1) {	//next & last
			ul.append(
				$('<li>').append(
					$('<a>').html('next >').attr('href', 'javascript:' + this.id + '.getPage(' + (this.page + 1) + ')')));
			ul.append(
				$('<li>').append(
					$('<a>').html('last >>').attr('href', 'javascript:' + this.id + '.getPage(' + (this.pageCount - 1) + ')')));
		}
		$('#' + this.pagerId).show();
	}

	this.setupHeadings = function () {
		this.headings = [];

		$(e).find('tbody > tr > th, thead > tr > th').each(function (i, th) {
			var h = { 
				bind: $(this).attr('bind'),
				format: $(this).attr('format'),
				type: $(this).attr('type'),
				maxlength: $(this).attr('maxlength'),
				maxlengthalign: $(this).attr('maxlengthalign'),
				cellcss: $(this).attr('cellcss'),				
				cellstyle: $(this).attr('cellstyle'),
				groupby: $(this).attr('groupby') 				
			};
			if (!h.bind)
				h.bind = $(this).html();
			_this.headings[_this.headings.length] = h;
		});

	}
	this.getSelectedIds = function () {
		var l = [];
		$('input:checkbox:checked.' + this.id + '-selector').each(function () { 
			l[l.length] = $(this).attr('data-id');
		});		
		return l;
	}
	this.setSelectedIds = function (l) {
		if (l == null)
			return;
		this.selectedIds = l;
		$('input:checkbox.' + this.id + '-selector').each(function () {
			if (l.indexOf($(this).attr('data-id')) != -1)
				$(this).attr('checked', 'checked');
			else
				$(this).removeAttr('checked');
		});
		return l;
	}
	this.setupHeadings();
	if (!this.delayLoading) {
		this.getData();
	}
}

$(function () {
	$('table.ajax-grid').each(function () {
		var id = $(this).attr('id');
		window[id] = new ajaxGrid(this);		
	});
});